#include "databuffer.h"

#include "core/coredefine.h"
#include <QCryptographicHash>
#include <QDebug>


DataBuffer::DataBuffer(QObject* parent)
    : QObject(parent)
{
    DEBUG_FUNC;
}

DataBuffer::~DataBuffer()
{
    DEBUG_FUNC;
}

void DataBuffer::pushData(const QByteArray& data)
{
    buffer_.append(data);
    checkReady();
}

void DataBuffer::checkReady()
{
    int index1 = buffer_.indexOf(CHAR_CMD_BEGIN);
    if (-1 == index1)
        return;

    int index2 = buffer_.indexOf(',', index1+1);
    if (-1 == index2)
        return;

    QString strCMD = buffer_.mid(index1+1, index2-index1-1);

    // 命令不存在则丢弃，寻找下一个 CHAR_CMD_BEGIN 字符的位置
    if (!isExistTcpCmdName(strCMD))
    {
        qWarning() << "CMD name:" << strCMD << "not exists, ignore CHAR_CMD_BEGIN!";
        buffer_ = buffer_.mid(index1 + 1);
        checkReady();
        return;
    }

    int index3 = buffer_.indexOf(',', index2+1);
    if (-1 == index3)
        return;

    QString md5Received = buffer_.mid(index2+1, index3-index2-1);

    if (32 != md5Received.size())
    {
        buffer_ = buffer_.mid(index2 + 1);  // 可能md5中有 CHAR_CMD_BEGIN 符号，所以只丢弃命令部分
        qWarning() << __FUNCTION__ << "wrong MD5 size:" << md5Received.size() << "ignore cmd word.";
        qDebug() << __FUNCTION__ << "now buffer_:" << buffer_;
        checkReady();
        return;
    }

    int index4 = buffer_.indexOf(',', index3+1);
    if (-1 == index4)
        return;

    long long dataSize = buffer_.mid(index3+1, index4-index3-1).toLongLong();
    if (0 == dataSize)
    {
        buffer_ = buffer_.mid(index4 + 1);
        qWarning() << __FUNCTION__ << "dataSize is 0, ignore it.";
        qDebug() << __FUNCTION__ << "now buffer_:" << buffer_;
        checkReady();
        return;
    }

    if (buffer_.size() - index4 - 1 < dataSize)  // 数据还没接收完
    {
        qDebug() << __FUNCTION__ << "Data didn't receive finshed, wait for next data.";
        return;
    }

    QByteArray data = buffer_.mid(index4+1, dataSize);
    QString md5Hashed = QCryptographicHash::hash(data, QCryptographicHash::Md5).toHex();

    if (md5Received == md5Hashed)
    {
        emit receiveOne(strCMD, data);
    }
    else
    {
        qWarning() << "Received wrong MD5, ignore it. Received MD5:" << md5Received << "Wished MD5:" << md5Hashed;
    }

    buffer_ = buffer_.mid(index3 + dataSize + 1);

    // 继续检查
    checkReady();
}
